package net.bithappens.hnqe.scratchpad;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringWriter;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Calendar;

import javax.xml.transform.stream.StreamSource;

import net.bithappens.hnqe.IllegalParamException;
import net.bithappens.hnqe.graph.EntryProperty;
import net.bithappens.hnqe.graph.EntryValue;
import net.bithappens.hnqe.graph.GraphElement;
import net.bithappens.hnqe.graph.GraphNode;
import net.bithappens.hnqe.graph.GraphRelation;
import net.bithappens.hnqe.graph.GraphRelationMember;
import net.bithappens.hnqe.impl.cache.schema.SchemaLoader;
import net.bithappens.hnqe.impl.rest.provider.CalendarJsonAddapter;
import net.bithappens.hnqe.impl.rest.provider.EntryValueJsonAddapter;
import net.bithappens.hnqe.impl.rest.provider.GraphElementJsonAddapter;
import net.bithappens.hnqe.impl.rest.provider.GraphRelationMemberJsonAddapter;
import net.bithappens.hnqe.query.Instance;
import net.bithappesn.hnqe.traverse.GraphPath;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class TestRest {

	public static void main(String[] args) throws Exception {
		
//		pushNode();
//		pushRelation();
//		deleteGraphEntry();
		
//		pushRelation();
//		
//		getNodeByUri();
//		getRelationByUri();
//		getIncidentRelation();
//		getNeighbor();
		
//		findRelation();
//		findExactRelation();
//		findPath();
		
		runQuery();
	}


	private static void pushNode() throws Exception {
		String urlString = "http://localhost:9998/hnqe/modify/pushNode/soaf/"
				+ URLEncoder.encode("http://someUri.com/armin", "UTF-8") + "?clearIfExist=true&tryKeyMatch=true";

		URL url = new URL(urlString);
		HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
		httpCon.setDoOutput(true);
		httpCon.setRequestMethod("PUT");
		httpCon.setRequestProperty("Content-Type", "application/json");

		GraphNode person = new GraphNode("person", new URI("http://someUri.com/armin"), null);
		person.setNodeClass("person");
		person.addProperty("name", EntryValue.createEntryValue("Armin Gruber"));
		person.addProperty("company", EntryValue.createEntryValue("Bithappens"));

		OutputStreamWriter out = new OutputStreamWriter(httpCon.getOutputStream());

		Gson gson = new GsonBuilder()
			.registerTypeAdapter(GraphRelationMember.class, new GraphRelationMemberJsonAddapter())
			.create();

		out.write(gson.toJson(person));

		out.close();

		System.out.println(">" + httpCon.getResponseCode());
		
		httpCon.disconnect();
	}

	private static void pushRelation() throws Exception {
		String urlString = "http://localhost:9998/hnqe/modify/pushRelation/soaf/" + 
				URLEncoder.encode("http://someUri.com/relation/first_rel", "UTF-8") + "?clearIfExist=true&tryKeyMatch=true";

		URL url = new URL(urlString);
		HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
		httpCon.setDoOutput(true);
		httpCon.setRequestMethod("PUT");
		httpCon.setRequestProperty("Content-Type", "application/json");

		GraphNode person = new GraphNode("person", new URI("http://someUri.com/armin"), null);
		person.setNodeClass("person");
		person.addProperty("name", EntryValue.createEntryValue("Armin Gruber"));
		person.addProperty("company", EntryValue.createEntryValue("Bithappens"));

		GraphNode service = new GraphNode("service", new URI("http://someUri.com/service/stock"), null);
		service.setNodeClass("service");
		service.addProperty("name", EntryValue.createEntryValue("sock"));
		service.addProperty("license", EntryValue.createEntryValue("free"));

		GraphRelation relation = new GraphRelation("provideService", new URI("http://someUri.com/relation/first_rel"), null);
		relation.addEntry(person);
		relation.addEntry(service);
		relation.addProperty("type", EntryValue.createEntryValue("testType"));
		
		OutputStreamWriter out = new OutputStreamWriter(httpCon.getOutputStream());

		Gson gson = new GsonBuilder().registerTypeAdapter(GraphRelationMember.class, new GraphRelationMemberJsonAddapter()).create();

		out.write(gson.toJson(relation));

		out.close();

		System.out.println(">" + httpCon.getResponseCode());
		
		httpCon.disconnect();
	}

	private static void deleteGraphEntry() throws Exception {
		String urlString = "http://localhost:9998/hnqe/modify/graphEntry/soaf/"	+ URLEncoder.encode("http://someUri.com/service/stock", "UTF-8");

		URL url = new URL(urlString);
		HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
		httpCon.setDoOutput(true);
		httpCon.setRequestMethod("DELETE");
		httpCon.setRequestProperty("Content-Type", "application/json");

		System.out.println(">" + httpCon.getResponseCode());
		
		httpCon.disconnect();
	}

	
	private static void getNodeByUri() throws Exception {
		
		String urlString = "http://localhost:9998/hnqe/traverse/node/soaf/"	+ URLEncoder.encode("http://someUri.com/armin", "UTF-8");

		URL url = new URL(urlString);
		HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
		httpCon.setDoOutput(true);
		httpCon.setRequestMethod("GET");
		httpCon.setRequestProperty("Content-Type", "application/json");

		BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpCon.getInputStream()));
		String line;
		String json = "";
        while ((line = bufferedReader.readLine()) != null) {
           json += line;
        }
        bufferedReader.close();
		
        Gson gson = new Gson();
        GraphNode graphNode = gson.fromJson(json, GraphNode.class);
        
		System.out.println(">" + httpCon.getResponseCode());
		System.out.println(graphNode);
		
		httpCon.disconnect();
	}

	private static void getRelationByUri() throws Exception {
		
		String urlString = "http://localhost:9998/hnqe/traverse/relation/soaf/"	+ 
				URLEncoder.encode("http://someUri.com/relation/first_rel", "UTF-8");

		URL url = new URL(urlString);
		HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
		httpCon.setDoOutput(true);
		httpCon.setRequestMethod("GET");
		httpCon.setRequestProperty("Content-Type", "application/json");

		BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpCon.getInputStream()));
		String line;
		String json = "";
        while ((line = bufferedReader.readLine()) != null) {
           json += line;
        }
        bufferedReader.close();
		
        Gson gson = new GsonBuilder()
			.registerTypeAdapter(GraphRelationMember.class, new GraphRelationMemberJsonAddapter())
			.create();
        
        GraphRelation graphRelation = gson.fromJson(json, GraphRelation.class);
        
		System.out.println(">" + httpCon.getResponseCode());
		System.out.println(graphRelation);
			
		httpCon.disconnect();
	}

	private static void getIncidentRelation() throws Exception {
		
		GraphNode person = new GraphNode("person", new URI("http://someUri.com/armin"), null);
		person.setNodeClass("person");
		person.addProperty(new EntryProperty("name", EntryValue.createEntryValue("Armin Gruber")));
		person.addProperty(new EntryProperty("company", EntryValue.createEntryValue("Bithappens")));

		Gson gson = new GsonBuilder().registerTypeAdapter(GraphRelationMember.class, new GraphRelationMemberJsonAddapter()).create();
		String gsonString = gson.toJson(person);
		
		String urlString = "http://localhost:9998/hnqe/traverse/incidentRelations/soaf?incidentAsJson=" + 
				URLEncoder.encode(gsonString, "UTF-8");

		URL url = new URL(urlString);
		HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
		httpCon.setDoOutput(true);
		httpCon.setRequestMethod("GET");
		httpCon.setRequestProperty("Content-Type", "application/json");

		
		BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpCon.getInputStream()));
		String line;
		String json = "";
        while ((line = bufferedReader.readLine()) != null) {
           json += line;
        }
        bufferedReader.close();
		        
        GraphRelation[] graphRelations = gson.fromJson(json, GraphRelation[].class);
        
		System.out.println(">" + httpCon.getResponseCode());
		for(GraphRelation relation : graphRelations){
			System.out.println(relation);
		}
		
		
		httpCon.disconnect();
	}
	
	private static void getNeighbor() throws Exception {
		
		GraphNode person = new GraphNode("person", new URI("http://someUri.com/armin"), null);
		person.setNodeClass("person");
		person.addProperty(new EntryProperty("name", EntryValue.createEntryValue("Armin Gruber")));
		person.addProperty(new EntryProperty("company", EntryValue.createEntryValue("Bithappens")));

		Gson gson = new GsonBuilder().registerTypeAdapter(GraphRelationMember.class, new GraphRelationMemberJsonAddapter()).create();
		String gsonString = gson.toJson(person);
		
		String urlString = "http://localhost:9998/hnqe/traverse/neighbors/soaf?incidentAsJson=" + 
				URLEncoder.encode(gsonString, "UTF-8");

		URL url = new URL(urlString);
		HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
		httpCon.setDoOutput(true);
		httpCon.setRequestMethod("GET");
		httpCon.setRequestProperty("Content-Type", "application/json");
		
		BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpCon.getInputStream()));
		String line;
		String json = "";
        while ((line = bufferedReader.readLine()) != null) {
           json += line;
        }
        bufferedReader.close();
		        
        GraphRelationMember[] graphRelationMembers = gson.fromJson(json, GraphRelationMember[].class);
        
		System.out.println(">" + httpCon.getResponseCode());
		for(GraphRelationMember neighbor : graphRelationMembers){
			System.out.println(neighbor);
		}
		
		
		httpCon.disconnect();
	}
	
	
	
	private static void findRelation() throws Exception {
		
		GraphNode person = new GraphNode("person", new URI("http://someUri.com/armin"), null);
		person.setNodeClass("person");
		person.addProperty(new EntryProperty("name", EntryValue.createEntryValue("Armin Gruber")));
		person.addProperty(new EntryProperty("company", EntryValue.createEntryValue("Bithappens")));

		GraphNode service = new GraphNode("service", new URI("http://someUri.com/service/stock"), null);
		service.setNodeClass("service");
		service.addProperty(new EntryProperty("name", EntryValue.createEntryValue("stock")));
		service.addProperty(new EntryProperty("license", EntryValue.createEntryValue("free")));

		
		GraphRelationMember[] entries = new GraphRelationMember[]{person, service}; 
		
		Gson gson = new GsonBuilder().registerTypeAdapter(GraphRelationMember.class, new GraphRelationMemberJsonAddapter()).create();
		String gsonString = gson.toJson(entries);
		
		String urlString = "http://localhost:9998/hnqe/traverse/findRelation/soaf?incidentAsJson=" + 
				URLEncoder.encode(gsonString, "UTF-8");

		URL url = new URL(urlString);
		HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
		httpCon.setDoOutput(true);
		httpCon.setRequestMethod("GET");
		httpCon.setRequestProperty("Content-Type", "application/json");
		
		BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpCon.getInputStream()));
		String line;
		String json = "";
        while ((line = bufferedReader.readLine()) != null) {
           json += line;
        }
        bufferedReader.close();
		        
        GraphRelation[] graphRelations = gson.fromJson(json, GraphRelation[].class);
        
		System.out.println(">" + httpCon.getResponseCode());
		for(GraphRelation relation : graphRelations){
			System.out.println(relation);
		}
		
		
		httpCon.disconnect();
	}
	
	private static void findExactRelation() throws Exception {
		
		GraphNode person = new GraphNode("person", new URI("http://someUri.com/armin"), null);
		person.setNodeClass("person");
		person.addProperty(new EntryProperty("name", EntryValue.createEntryValue("Armin Gruber")));
		person.addProperty(new EntryProperty("company", EntryValue.createEntryValue("Bithappens")));

		GraphNode service = new GraphNode("person", new URI("http://someUri.com/service/stock"), null);
		service.setNodeClass("service");
		service.addProperty(new EntryProperty("name", EntryValue.createEntryValue("stock")));
		service.addProperty(new EntryProperty("license", EntryValue.createEntryValue("free")));

		
		GraphRelationMember[] entries = new GraphRelationMember[]{person, service}; 
		
		Gson gson = new GsonBuilder().registerTypeAdapter(GraphRelationMember.class, new GraphRelationMemberJsonAddapter()).create();
		String gsonString = gson.toJson(entries);
		
		String urlString = "http://localhost:9998/hnqe/traverse/findExactRelation/soaf?incidentAsJson=" + 
				URLEncoder.encode(gsonString, "UTF-8");

		URL url = new URL(urlString);
		HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
		httpCon.setDoOutput(true);
		httpCon.setRequestMethod("GET");
		httpCon.setRequestProperty("Content-Type", "application/json");
		
		BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpCon.getInputStream()));
		String line;
		String json = "";
        while ((line = bufferedReader.readLine()) != null) {
           json += line;
        }
        bufferedReader.close();
		        
        GraphRelation[] graphRelations = gson.fromJson(json, GraphRelation[].class);
        
		System.out.println(">" + httpCon.getResponseCode());
		for(GraphRelation relation : graphRelations){
			System.out.println(relation);
		}
		
		
		httpCon.disconnect();
	}
		
	private static void findPath() throws IllegalParamException, URISyntaxException, IOException {

		GraphNode start = new GraphNode("Service", new URI("http://sose.com/node/service31"), null);
		GraphNode end = new GraphNode("SoftwareBasedService", new URI("http://sose.com/node/softwarebasedservice14"), null); 
		
		Gson gson = new GsonBuilder()
			.registerTypeAdapter(GraphRelationMember.class, new GraphRelationMemberJsonAddapter())
			.create();
		
		String startString = gson.toJson(start);
		String endString = gson.toJson(end);
		
		Object[] params = new Object[]{"TypeA", "TypeB"};
				
		String urlString = "http://localhost:9998/hnqe/traverse/findPath/sose?" +
			"startAsJson=" + URLEncoder.encode(startString, "UTF-8") + "&" +
			"endAsJson=" + URLEncoder.encode(endString, "UTF-8") + "&" +
			"pathValidatorId=" + "SimpleTypeValidator" + "&" +
			"validatorParamsAsJson=" + URLEncoder.encode(gson.toJson(params, Object[].class), "UTF-8") + "&" +
			"maxPathLength=" + 5 + "&" +
			"searchForAll=" + false;
			
		URL url = new URL(urlString);
		HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
		httpCon.setDoOutput(true);
		httpCon.setRequestMethod("GET");
		httpCon.setRequestProperty("Content-Type", "application/json");
		
		BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpCon.getInputStream()));
		String line;
		String json = "";
        while ((line = bufferedReader.readLine()) != null) {
           json += line;
        }
        bufferedReader.close();
		
        System.out.println(json);
        
        GraphPath[] graphPaths = gson.fromJson(json, GraphPath[].class);
        
		System.out.println(">" + httpCon.getResponseCode());
		for(GraphPath relation : graphPaths){
			System.out.println(relation);
		}
		
		
		httpCon.disconnect();
		
	}
		
	
	private static void runQuery() throws Exception {

//		BufferedReader reader = new BufferedReader(new FileReader("I:\\Armin\\JAVAProjects\\HyperNetworkQueryEngine\\Scratch\\soseQuery.xml"));
//		BufferedReader reader = new BufferedReader(new FileReader("soseQuery.xml"));
		
		InputStream queryXML = new StreamSource(TestRest.class.getResourceAsStream("soseQuery.xml")).getInputStream();

		final char[] buffer = new char[0x10000];
		StringBuilder out = new StringBuilder();
		Reader in = new InputStreamReader(queryXML, "UTF-8");
		try {
		  int read;
		  do {
		    read = in.read(buffer, 0, buffer.length);
		    if (read>0) {
		      out.append(buffer, 0, read);
		    }
		  } while (read>=0);
		} finally {
		  in.close();
		  queryXML.close();
		}

		System.out.println(out.toString());
		
		String urlString = "http://localhost:9998/hnqe/query/sose?minSize=0&query=" + 
				URLEncoder.encode(out.toString().replaceAll("\\s+", " ").trim(), "UTF-8");

		URL url = new URL(urlString);
		HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
		httpCon.setDoOutput(true);
		httpCon.setRequestMethod("GET");
		httpCon.setRequestProperty("Content-Type", "application/json");
		
		BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpCon.getInputStream()));
		String line;
		String json = "";
        while ((line = bufferedReader.readLine()) != null) {
           json += line;
        }
        bufferedReader.close();
		httpCon.getInputStream().close();
		
        Gson gson = new GsonBuilder()
        	.registerTypeAdapter(GraphRelationMember.class, new GraphRelationMemberJsonAddapter())
			.registerTypeAdapter(GraphElement.class, new GraphElementJsonAddapter())
			.registerTypeAdapter(EntryValue.class, new EntryValueJsonAddapter())
			.registerTypeAdapter(Calendar.class, new CalendarJsonAddapter())
        	.create();
        Instance[] instanceSets = gson.fromJson(json, Instance[].class);
        
		System.out.println(">" + httpCon.getResponseCode());
		
		httpCon.disconnect();
		
		for(Instance instance : instanceSets){
			
			System.out.println("\n\n\n######################################################\n\n\n");
			
			System.out.println(instance.getInstanceForId("S").toString());
			System.out.println(instance.getInstanceForId("SBS").toString());
			System.out.println(instance.getInstanceForId("HPS").toString());
			
			System.out.println(instance.getInstanceForId("R1").toString());
			System.out.println(instance.getInstanceForId("R2").toString());
			
		}		
		
	}


}



